#ifndef OPT_SWITCH_H
#define OPT_SWITCH_H

/*! \ingroup qgetopt
    \brief This enum type defines the switch style.

    \b continueRunning means that the program will continue running after processing the switch.

    \b immediateStop means that the program will stop once the switch has been processed.
 */
enum switchStyle{continueRunning, immediateStop};

#include <QtCore>

#include "optManager.h"
#include "optArgument.h"

/*! \ingroup qgetopt
    \brief The OptSwitch class holds details of a switch.

    This class is a \em private class and instances may only be created by the OptManager object which is a friend class.

    A switch will have a \em fullName, it may also have an \em abbrev which must be a single letter or a single number.
    A switch may have any number of arguments, either mandatory or optional. All optional arguments
    are contained in square brackets. A switch may also be associated with an \em actionMethod, which will be a
    pointer to a method and will be run during the OptManager::pharse() phase of the program.
    In addition it may have an \em exitMethod, which is a pointer to a method and will be run during the
    OptManager::close() phase. Finaly the switch will have a \em style flag which may be set to either
    \em continueRunning or \em immediateStop, if it is set to \em immediateStop then the application
    will stop once the \em actionMethod has been executed.

    A switch can be created by calling the OptManager::addSwitch() method.
    This method returns a pointer to the instance of the switch object which allows any of the public methods to be called.
    Thus by calling addDescription() a description can be added to a switch which will be displayed in the help screen.

 * \attention This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * \attention This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * \attention You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307  USA
 *
   \author    Graeme
   \date Copyright (C) 2008-9  Graeme Foster
 */
class OptSwitch
{
   //! OptSwitch is a private class with all interaction through OptManager
   /*! The OptManager makes available the following methods:
     <table><tr><td>addSwitch()</td><td>to create a switch</td></tr>
       <tr><td>getSwitchDetails()</td><td>which returns the arguments as a QStringList that were provided for a particular switch,
       if the switch was not provided, or no arguments were given then an empty QStringList is returned.</td></tr>
     </table>
   */
   friend class OptManager;
   /*! This is an overloaded member function, provided for convenience. */
   friend QTextStream & operator<< ( QTextStream & stream, const OptSwitch & os );

   private:
      //! \internal The short name of the switch, this is a single letter
      QChar _shortName;
      //! \internal The long name of the switch
      QString _longName;
      //! \internal The detailed description of the switch
      QString _description;
      //! \internal The list of arguments that are required
      QList <OptArgument *> _mandatoryArgList;
      //! \internal The list of arguments that may also be provided
      QList <OptArgument *> _optionalArgList;
      //! \internal The list of arguments that have actually been provided
      QStringList _actualArgList;
      //! \internal The function that will be executed at start-up if the switch has been selected
      ActionFuncPtr _actionFn;
      //! \internal The function that will be executed at wrap-up if the switch has been selected
      CloseFuncPtr _closeFn;
      //! \internal Flag to indicate it the program should abort after running its own functions if the switch is provided
      switchStyle _style;
   public:
      //!  Add a detailed description to the switch
      /*! This description will be displayed in the help file.
          The switch instance is returned from addSwitch() for example:
          \code
             QString detail;
             OptManager * om = OptManager::getOptMgr(ProgName);
             detail = QObject::tr("This will backupthe log file before any changes are made to it.");
             om->addSwitch("back-up",backup, 'b', "FILE")->addDescription(detail);
          \endcode
      */
      void addDescription(QString detail){_description=detail;}
      //! return the details of a specific arguments received.
      /*! The argument if it exists will be returned. */
      inline QString getArg(int cnt) const
      {
         if ((cnt >= 0) && (cnt < actualArgCnt()))
            return _actualArgList.at(cnt);
         else
            return QString();
      }
      //! return the details of arguments received.
      /*! The arguments are returned as a string list. */
      QStringList argList() const {return _actualArgList;}
      int actualArgCnt()const {return _actualArgList.size();}
   private:
      //! \internal Private constructor instances will only be created by the friend class OptManager
      OptSwitch(QChar abbrev
               ,QString fullName
               ,QString args
               ,ActionFuncPtr actionMethod
               ,CloseFuncPtr exitMethod
               ,switchStyle style=continueRunning
               );
      //! \internal Private copy constructor for singleton class
      OptSwitch(const OptSwitch&);
      //! \internal Return the short switch name
      QChar abbrev(){return _shortName;}
      //! \internal Return the long switch name
      QString name(){return _longName;}
      //! \internal Add the argument to the list of arguments provided
      void addActualArg(QString arg){_actualArgList.append(arg);}
      //! \internal Return the number of mandaroty arguments
      int mArgCnt(){return _mandatoryArgList.size();}
      //! \internal Return the number of optional arguments
      int oArgCnt(){return _optionalArgList.size();}
      //! \internal Return the total number of arguments
      int argCnt(){return mArgCnt()+oArgCnt();}
      //! \internal Return the true if this is a conclude switch
      bool finishProcessing(){return _style;}
      //! \internal Execute the switches action method
      void execute(){if (_actionFn)_actionFn(this);}
      //! \internal Execute the switches close method
      void close(){if (_closeFn) _closeFn();}
      //! \internal Return brief details of the switch, its name and the arguments
      QString brief();
      //! \internal Return the argument list for the switch
      QString fullArgList();
      //! \internal Return the details of the switch
      QString help();
      //! \internal Return the details that have been provided, essentially the actual arguments
      QString dump();
      //! \internal Format the string to be no more than 80 character wide
      QString format80(const QString & msg);
};

#endif
